using System;
using System.Threading;
using System.Windows.Forms;

namespace Pegasus.Windows.Forms
{
	/// <summary>
	/// This class will show the given form type on a background thread so that you can use the forground thead
	/// for other things.  This class should be moved to Pegasus at some point.
	/// </summary>
	/// <typeparam name="FormType"></typeparam>
	public class BackgroundDialog<FormType>
			where FormType : Form, new()
	{
		// Local Instance Values
		private FormType m_dialog = null;
		private DialogResult m_dialogResult = DialogResult.None;
		private AutoResetEvent m_initializeEvent = new AutoResetEvent( false );

		/// <summary>
		/// Initializes a new instance of the <see cref="BackgroundDialog&lt;FormType&gt;"/> class.
		/// </summary>
		public BackgroundDialog()
		{
		}

		/// <summary>
		/// Gets the form.
		/// </summary>
		/// <value>The form.</value>
		public FormType Form
		{
			get
			{
				return m_dialog;
			}
		}

		/// <summary>
		/// Gets the dialog result.
		/// </summary>
		/// <value>The dialog result.</value>
		public DialogResult DialogResult
		{
			get
			{
				return m_dialogResult;
			}
		}

		/// <summary>
		/// Shows the Dialog on background thread.
		/// </summary>
		public void ShowDialog()
		{
			Thread workerThread = new Thread( new ParameterizedThreadStart( WorkingThreadProc ) );
			workerThread.Name = "Pegasus.Windows.Forms.BackgroundDialog";
			workerThread.Start( null );

			m_initializeEvent.WaitOne();
		}

		/// <summary>
		/// Closes the dialog
		/// </summary>
		public void Close()
		{
			m_dialog.Invoke( new CloseHandler( m_dialog.Close ) );
		}

		/// <summary>
		/// The thread proc for the worker thead
		/// </summary>
		/// <param name="arg">The arg.</param>
		private void WorkingThreadProc( object arg )
		{
			m_dialog = new FormType();
			
			m_initializeEvent.Set();
			
			m_dialogResult = m_dialog.ShowDialog();
		}

		/// <summary>
		/// Delegate for the close method.
		/// </summary>
		private delegate void CloseHandler();
	}
}
